package com.cgy.utils.spider.element;

import com.cgy.utils.spider.type.ElementType;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import com.cgy.utils.spider.template.Field;
import com.cgy.utils.spider.template.Template;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;

/**
 * @author CHTK
 */
@Slf4j
public class TemplateElement extends AbstractElement{

    protected List<Template> template = Lists.newArrayList();

    private static final ElementType ELEMENT_TYPE = ElementType.TEMPLATE;

    public TemplateElement() {
        super(ELEMENT_TYPE);
    }

    @Override
    public AbstractElement element() {
        if (null == template || template.isEmpty()) {
            log.error("template does not null");
            return this;
        }
        for (Template template1 : template) {
            List<Field> fields = template1.getFields();
            for (Field field : fields) {
                addElement(field.getName(), field.getRegex(), ELEMENT_TYPE);
            }
        }
        return this;
    }

    public TemplateElement(boolean isDebugger) {
        super(ELEMENT_TYPE);
        setDebugger(isDebugger);
    }

    public TemplateElement template(String json) {
        Gson gson = new GsonBuilder().serializeNulls().create();
        Template template = gson.fromJson(json, Template.class);
        this.template.add(template);
        return this;
    }

    public TemplateElement template(Template template, Template... other) {
        this.template.add(template);
        for (Template template1 : other) {
            this.template.add(template1);
        }
        return this;
    }

    public TemplateElement template(Template template) {
        this.template.add(template);
        return this;
    }

    public TemplateElement template(File file, File... files) {
        makeTemplate(file);
        for (File file1 : files) {
            makeTemplate(file1);
        }
        return this;
    }

    public TemplateElement template(File file) {
        makeTemplate(file);
        return this;
    }

    @Override
    public AbstractElement beforeElement() {
        return super.beforeElement();
    }

    /**
     *
     * @param file
     */
    private void makeTemplate(File file) {
        try (FileInputStream fileInputStream = FileUtils.openInputStream(file)) {
            JAXBContext jaxbContext = JAXBContext.newInstance(Template.class);
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            Object unmarshal = unmarshaller.unmarshal(fileInputStream);
            this.template.add((Template) unmarshal);
        } catch (IOException e) {
            log.error("file open exception");
            e.printStackTrace();
        } catch (JAXBException e) {
            log.error("template unmarshal exception");
            e.printStackTrace();
        }
    }
}
